package org.jugile.util;

/*

Copyright (C) 2007-2011 Jukka Rahkonen  email: jukka.rahkonen@iki.fi

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*/

import java.util.ArrayList;
import java.util.List;

/**
 * ""
 * 
 * @author jukka.rahkonen@iki.fi
 */
public class WikiBlock extends Jugile {

	enum State {
		LINESTART,
		LINE,
	}

	public class Line {
		private String line;
		public Line(String line) { 
			this.line = line;
		}
		public char charAt(int idx) {
			if (idx > line.length() || idx < 0) return 0;
			return line.charAt(idx); 
		}
		public int length() { return line.length(); }
		public int indent() {
			for (int i = 0; i < line.length(); i++) {
				if (!Character.isWhitespace(line.charAt(i))) return i;
			}
			return line.length(); // all whites
		}
		public boolean equals(String str, int idx) {
			if ((idx + str.length()) > line.length()) return false;
			if (str.equals(line.substring(idx, idx+str.length()))) return true;
			return false;
		}
	}
	
	public static void main(String args[]) {
		// luetaan wiki.txt
		Blob wiki = new Blob("wiki.txt");
		WikiBlock w = new WikiBlock();
		Node n = w.parse(wiki);
		print(n.render());
	}
	
	public Node parse(Blob blob) {
		Node root = new Node("div");
		Node n = root.add("p");
		Node b = null;
		Node i = null;
		Node list = null;

		int indent = 0;
		for (String linetxt : blob.getLines()) {
			if (empty(linetxt)) {
				n = root.add("p"); 
				continue;
			}
			Line line = new Line(linetxt);
			// count indent - not fully empty line
			int ind = line.indent();
			State st = State.LINESTART;
			Buffer buf = new Buffer();
			for (int idx = ind; idx < line.length(); idx++) {
				char ch = line.charAt(idx);
				if (ch == '\\') {
					idx++; // add next char to buffer as it is
					ch = line.charAt(idx);
					if (ch != 0) buf.add(ch);
					st = State.LINE;
					continue;
				}
				if (st == State.LINESTART) {
					st = State.LINE;
					if (ch == '-') {
						list = findListNode(n,ind);
						if (list == null) list = n.add("ul").attr("ind", ""+ind);
						n = list.add("li");
						continue;
					}
					if (Character.isDigit(ch)) {
						if (line.charAt(idx+1) == '.') {
							list = findListNode(n,ind);
							if (list == null) list = n.add("ol").attr("ind", ""+ind);
							n = list.add("li");
							idx++;
							continue;
						}
					}
				}
				if (ch == '*') {
					n.add("",buf.toString());
					buf = new Buffer();
					if (b != null) {
						// terminate b 
						n = b.parent();
						b = null;
					} else {
						b = n.add("b");
						n = b;
					}
					continue;
				}
				if (ch == '/') {
					if (line.charAt(idx+1) == '/') {
						n.add("",buf.toString());
						buf = new Buffer();
						if (i != null) {
							// terminate i
							n = i.parent();
							i = null;
						} else {
							i = n.add("i");
							n = i;
						}
						idx++;
						continue;
					}
				}
				if (ch == '[') {
					// luetaan kaikki sulkumerkkiin asti
					int end = linetxt.indexOf(']', idx);
					if (end > idx) {
						n.add("", buf.toString());
						buf = new Buffer();
						String url = linetxt.substring(idx+1, end);
						Node a = n.add("a", url).attr("href", url);
						idx = end;
						continue;
					}
				}
				if (ch == 'h') {
					if (line.equals("http://", idx)) {
						n.add("", buf.toString());
						buf = new Buffer();
						int end = linetxt.indexOf(" ", idx+7);
						if (end < idx) end = linetxt.length();
						String url = linetxt.substring(idx, end);
						Node a = n.add("a", url).attr("href", url);
						idx = end;
						continue;
					}
				}
				buf.add(ch); // default case
			}
			n.add("", buf.toString()); // end of line
		}
		// cleanup
		root.traverse(new Cleaner());
		return root;
	}

	private Node findListNode(Node n, int indent) {
		if ("ul".equals(n.name()) || "ol".equals(n.name())) {
			Integer ind = Integer.parseInt(n.attr("ind"));
			if (ind == indent) return n;
		}
		Node p = n.parent();
		if (p == null) return null;
		return findListNode(p, indent);
	}

	class Cleaner implements INodeTraverser {
		public void handle(Node n) {
			if ("p".equals(n.name())) if (n.isEmpty()) n.markDeleted();
			if ("ul".equals(n.name()) || "ol".equals(n.name())) {
				if (n.attr("ind") != null) {
					n.removeAttr("ind");
				}
			}
		}
		public void after(Node n) { }
		public void setIdx(int i, int size) {	}
		public int getIdx() { return 0; }
		public int getSize() { return 0; }
	}
}
